/*******************************************************************************
 * Copyright 2007, 2009 InnovaSoft SA http://www.innovasoft.biz/
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
 
package biz.innovasoft.nodb.index;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;

public class IndexManager implements Serializable {

	private static final long serialVersionUID = -1285170436221245303L;

	private String name;
	private Class<?> clazz;
	private boolean isRootIndex = false;
	private Map<String, IndexEntry> indexEntries = new HashMap<String, IndexEntry>();

	private Directory directory;
	
	private IndexManager parent;
	private List<IndexManager> childs = new ArrayList<IndexManager>();
	
	public IndexManager (Class<?> clazz) {
		this(clazz, clazz.getCanonicalName(), false);
	}
	
	public IndexManager (Class<?> clazz, boolean isRootIndex) {
		this(clazz, clazz.getCanonicalName(), isRootIndex);
	}
	
	public IndexManager(Class<?> clazz, String name, boolean isRootIndex) {
		this.name = name;
		this.clazz = clazz;
		this.isRootIndex = isRootIndex;
		initialize ();
	}

	public String getName() {
		return name;
	}
	
	public Class<?> getIndexClass() {
		return clazz;
	}
	
	public boolean isRootIndex() {
		return isRootIndex;
	}

	public void setParent (IndexManager parent) {
		this.parent = parent;
	}
	
	public IndexManager getParent () {
		return parent;
	}
	
	public void addChild (IndexManager child) {
		childs.add(child);
	}
	
	public List<IndexManager> getChilds() {
		return childs;
	}
	
	public boolean hasIndexEntries () {
		return (indexEntries.size() > 0);
	}
	
	public void addIndexEntry(IndexEntry entry) {
		indexEntries.put(entry.getIndexPath(), entry);
	}

	public IndexEntry getIndexEntry(String indexPath) {
		return indexEntries.get(indexPath);
	}
	
	public void removeIndexEntry (String indexPath) {
		if (indexEntries.containsKey(indexPath)) {
			indexEntries.remove(indexPath);
		}
	}

	public IndexEntry[] getIndexEntries() {
		return (IndexEntry[]) indexEntries.values().toArray(new IndexEntry[0]);
	}
	
	public IndexEntry[] getIndexEntries(boolean searchInParent) {
		if (searchInParent) {
			return (IndexEntry[])getIndexEntriesAsList(true).toArray(new IndexEntry[0]);
		}
		return getIndexEntries();
	}
	
	public List<IndexEntry> getIndexEntriesAsList(boolean searchInParent) {
		List<IndexEntry> entries = new ArrayList<IndexEntry>();
		if (indexEntries.size() == 0 && searchInParent) {
			if (parent == null) {
				return entries;
			}
			entries.addAll(parent.getIndexEntriesAsList(true));
			return entries;
		} 
		entries.addAll(indexEntries.values());
		return entries;
	}

	public boolean containsEntry(String indexPath) {
		return indexEntries.containsKey(indexPath);
	}

	public Directory getDirectory() {
		return directory;
	}
	
	public List<Directory> getDirectoriesFromChilds () {
		List<Directory>dirs = new ArrayList<Directory>();
		dirs.add(directory);
		for (IndexManager child : childs) {
			dirs.addAll(child.getDirectoriesFromChilds());
		}
		return dirs;
	}
	
	public void initialize () {
		directory = new RAMDirectory();
		try {
			IndexWriter writer = new IndexWriter(directory, new SimpleAnalyzer(), true,
					IndexWriter.MaxFieldLength.UNLIMITED);
			writer.close();
		} catch (Exception e) {}
	}

}
